using System;
using Castle.Windsor;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using NHibernate;
using Caramel.Linq;

namespace Caramel.NHibernate.Castle
{
	public class NHibernateInstaller : IWindsorInstaller
	{
		public NHibernateInstaller(global::NHibernate.Cfg.Configuration configuration)
		{
			this.Configuration = configuration;
		}

		protected global::NHibernate.Cfg.Configuration Configuration { get; private set; }

		#region IWindsorInstaller Members

		public void Install(global::Castle.Windsor.IWindsorContainer container, IConfigurationStore store)
		{
			container.
				Register(
					Component.
						For<global::NHibernate.Cfg.Configuration>().
						Instance(this.Configuration).
						LifeStyle.
						Singleton
				);

			container.
				Register(
					Component.
						For<ISessionFactory>().
						UsingFactoryMethod(k => k.Resolve<global::NHibernate.Cfg.Configuration>().BuildSessionFactory()).
						LifeStyle.
						Singleton
				);

			container.
				Register(
					Component.
						For<IUnitOfWorkFactory>().
						UsingFactoryMethod(k => new NHibernateUnitOfWorkFactory(k.Resolve<ISessionFactory>())).
						LifeStyle.
						Singleton
				);

			// Register our default repository for mapped types
			this.Configuration.
				ClassMappings.
				Each(
					c =>
					container.
						Register(
							Component.
								For(
									typeof(IRepository<>).
									MakeGenericType(c.MappedClass)
								).
								ImplementedBy(
									typeof(NHibernateRepository<>).
										MakeGenericType(c.MappedClass)
								).
								LifeStyle.
								Singleton
						)
				);
		}

		#endregion
	}
}
